package battle

import (
	"battle-server/manager"
	"battle-server/model"
	"fmt"
	"math/rand"
	"sort"
	"time"
)

// BattleSystem 战斗系统
type BattleSystem struct {
	Battle       *model.Battle      // 战斗实例
	CurrentRound int                // 当前回合
	ActionQueue  []*model.FightHero // 行动队列
	IsFinished   bool               // 战斗是否结束
	MaxRounds    int                // 最大回合数
	RNG          *rand.Rand         // 随机数生成器
}

// NewBattleSystem 创建新的战斗系统
func NewBattleSystem(battle *model.Battle) *BattleSystem {
	return &BattleSystem{
		Battle:       battle,
		CurrentRound: 0,
		ActionQueue:  make([]*model.FightHero, 0),
		IsFinished:   false,
		MaxRounds:    15, // 默认最大回合数
		RNG:          rand.New(rand.NewSource(time.Now().UnixNano())),
	}
}

// StartBattle 开始战斗
func (bs *BattleSystem) StartBattle() *BattleResult {
	// 初始化战斗
	bs.initBattle()

	// 记录战斗开始
	bs.logBattleAction("battle_start", 0, nil, nil, "战斗开始！")

	// 战斗主循环
	for !bs.IsFinished && bs.CurrentRound < bs.MaxRounds {
		bs.StartRound()
	}

	// 如果达到最大回合数但战斗未结束，判定为平局
	if bs.CurrentRound >= bs.MaxRounds && !bs.IsFinished {
		bs.logBattleAction("battle_draw", 0, nil, nil, "战斗达到最大回合数，判定为平局！")
		bs.Battle.Winner = 0 // 0表示平局
		bs.IsFinished = true
	}

	// 返回战斗结果
	return bs.generateBattleResult()
}

// 初始化战斗
func (bs *BattleSystem) initBattle() {
	bs.CurrentRound = 0
	bs.Battle.StartTime = time.Now()
	bs.Battle.Status = "in_progress"

	// 初始化所有英雄的状态
	for playerID, heroPositions := range bs.Battle.FightHeroes {
		for _, hero := range heroPositions {
			// 保存最大生命值
			hero.MaxHp = hero.CurrentHp

			// 初始化技能CD
			if hero.SkillCDs == nil {
				hero.SkillCDs = make(map[int]int)
			}

			// 确保英雄存活状态
			hero.IsAlive = true
			hero.PlayerId = playerID

			// 初始化行动状态
			hero.ActionTaken = false

			// 初始化buff和debuff数组
			if hero.Buffs == nil {
				hero.Buffs = make([]model.Effect, 0)
			}
			if hero.Debuffs == nil {
				hero.Debuffs = make([]model.Effect, 0)
			}

			// 初始化技能CD为0
			for _, skillID := range hero.Skills {
				hero.SkillCDs[skillID] = 0
			}
		}
	}
}

// StartRound 开始新回合
func (bs *BattleSystem) StartRound() {
	bs.CurrentRound++
	roundStartMsg := fmt.Sprintf("第%d回合开始", bs.CurrentRound)
	bs.logBattleAction("round_start", 0, nil, nil, roundStartMsg)

	// 重置所有英雄的行动状态
	bs.resetActionStatus()

	// 执行buff效果，deBuff效果,回合前执行：中毒，灼烧等dot
	bs.processStatusEffects()

	// 确定行动顺序
	bs.determineActionOrder()

	// 执行行动
	for _, hero := range bs.ActionQueue {
		if !hero.IsAlive || hero.ActionTaken {
			continue
		}

		// 检查控制状态
		if bs.isControlled(hero) {
			controlMsg := fmt.Sprintf("英雄 %s 被控制，无法行动", hero.HeroName)
			bs.logBattleAction("hero_controlled", hero.HeroId, nil, nil, controlMsg)
			hero.ActionTaken = true
			continue
		}

		// 执行英雄行动
		bs.executeHeroAction(hero)
		hero.ActionTaken = true

		// 检查战斗是否结束
		if bs.checkBattleEnd() {
			bs.IsFinished = true
			break
		}
	}

	// 回合结束处理
	bs.endRound()
}

// 确定行动顺序
func (bs *BattleSystem) determineActionOrder() {
	bs.ActionQueue = make([]*model.FightHero, 0)

	// 收集所有存活的英雄
	for _, heroPositions := range bs.Battle.FightHeroes {
		for _, hero := range heroPositions {
			if hero.IsAlive {
				bs.ActionQueue = append(bs.ActionQueue, hero)
			}
		}
	}

	// 按速度排序
	sort.Slice(bs.ActionQueue, func(i, j int) bool {
		return bs.ActionQueue[i].Speed > bs.ActionQueue[j].Speed
	})
}

// 重置所有英雄的行动状态
func (bs *BattleSystem) resetActionStatus() {
	for _, heroPositions := range bs.Battle.FightHeroes {
		for _, hero := range heroPositions {
			hero.ActionTaken = false
		}
	}
}

// 检查所有英雄的buffers和debuffs
func (bs *BattleSystem) processStatusEffects() {
	for _, playerHeros := range bs.Battle.FightHeroes {
		for _, hero := range playerHeros {
			if hero.IsAlive {
				// 检查buff效果
				bs.checkBuffEffects(hero)
				// 检查deBuff效果
				bs.checkDeBuffEffects(hero)
			}
		}

	}
}

// 检查buff效果
func (bs *BattleSystem) checkBuffEffects(hero *model.FightHero) {

}

// 检查deBuff效果
func (bs *BattleSystem) checkDeBuffEffects(hero *model.FightHero) {

}

// 检查英雄是否被控制
func (bs *BattleSystem) isControlled(hero *model.FightHero) bool {
	// 检查debuff中是否有控制效果
	for _, effect := range hero.Debuffs {
		if effect.Type == model.EffectDizzy || effect.Type == model.EffectFreeze {
			return true
		}
	}
	return false
}

// 执行英雄行动
func (bs *BattleSystem) executeHeroAction(hero *model.FightHero) {
	// 嘲讽效果，如果有嘲讽buff，那么修正目标 todo
	// 选择技能
	skillID := bs.selectSkill(hero)
	if skillID == 0 {
		// 如果没有可用技能，执行普通攻击
		bs.executeNormalAttack(hero)
	} else {
		// 执行技能
		bs.executeSkill(hero, skillID)
	}

	// 更新技能CD
	bs.updateSkillCDs(hero)
}

// 选择技能
func (bs *BattleSystem) selectSkill(hero *model.FightHero) int {
	// 优先选择二技能
	// 否则选择普通技能
	skillId := 0
	for _, skillID := range hero.Skills {
		if hero.SkillCDs[skillID] == 0 {
			skillId = skillID
		}
		if manager.IsSkillIsUltimate(skillId) {
			return skillId
		}
	}

	return 0 // 返回0表示没有可用技能
}

// 执行普通攻击
func (bs *BattleSystem) executeNormalAttack(attacker *model.FightHero) {
	// 选择目标
	target := bs.selectAttackTarget(attacker)
	if target == nil {
		bs.logBattleAction("attack_no_target", attacker.HeroId, nil, nil,
			fmt.Sprintf("英雄 %s 没有找到攻击目标", attacker.HeroName))
		return
	}

	// 计算伤害
	damage, isCrit := bs.calculateDamage(attacker, target, float64(attacker.Attack), false)

	// 应用伤害
	bs.applyDamage(attacker, target, damage)

	// 记录攻击日志
	critText := ""
	if isCrit {
		critText = "（暴击）"
	}

	attackMsg := fmt.Sprintf("英雄 %s 对英雄 %s 进行普通攻击%s，造成 %d 点伤害",
		attacker.HeroName, target.HeroName, critText, damage)

	bs.logBattleAction("hero_attack", attacker.HeroId, []int{target.HeroId}, nil, attackMsg)
}

// 执行技能
func (bs *BattleSystem) executeSkill(caster *model.FightHero, skillID int) {
	// 获取技能信息
	skill, err := manager.GteSkillById(skillID)
	if err != nil {
		return
	}

	// 设置技能CD
	skillCD := skill.Cooldown
	caster.SkillCDs[skillID] = skillCD

	// 获取技能目标
	targets := bs.getSkillTargets(caster, int(skill.TargetType))
	if len(targets) == 0 {
		bs.logBattleAction("skill_no_target", caster.HeroId, nil, []int{skillID},
			fmt.Sprintf("英雄 %s 释放技能 %s 没有找到目标", caster.HeroName, skill.SkillName))
		return
	}

	// 记录技能使用日志
	targetIds := make([]int, len(targets))
	for i, t := range targets {
		targetIds[i] = t.HeroId
	}

	skillMsg := fmt.Sprintf("英雄 %s 释放技能 %s", caster.HeroName, skill.SkillName)
	bs.logBattleAction("hero_skill", caster.HeroId, targetIds, []int{skillID}, skillMsg)

	// 技能工厂创建技能
	skillFactory := model.NewSkillFactory()
	executeSkill := skillFactory.CreateSkill(skillID)
	if executeSkill == nil {
		bs.logBattleAction("skill_no_exists", caster.HeroId, nil, []int{skillID},
			fmt.Sprintf("英雄 %s 释放技能 %s 没有对应技能类", caster.HeroName, skill.SkillName))
		return
	}

	// 执行技能
	executeSkill.Execute(caster, targets)

	// 执行技能效果
	bs.executeSkillEffect(targets)
}

func (bs *BattleSystem) executeSkillEffect(targets []*model.FightHero) {
	factory := model.NewEffectFactory()
	for _, target := range targets {
		// 执行buff
		for _, buff := range target.Buffs {
			executor, err := factory.CreateEffectExecutor(target, buff)
			if err != nil {
				continue
			}
			executor.Execute(target)
		}

		// 执行debuff
		for _, buff := range target.Debuffs {
			executor, err := factory.CreateEffectExecutor(target, buff)
			if err != nil {
				continue
			}
			executor.Execute(target)
		}

	}

}

// 生成效果ID
func (bs *BattleSystem) generateEffectID() int {
	return bs.RNG.Intn(10000) + 1
}

// 获取技能目标
func (bs *BattleSystem) getSkillTargets(caster *model.FightHero, targetType int) []*model.FightHero {
	// 根据技能类型选择不同的目标
	target := model.SkillTarget(targetType)

	switch target {
	case model.TargetEnemyFront: // 敌方前排
		return bs.getEnemyFrontRowTargets(caster)
	case model.TargetEnemyBack: // 敌方后排
		return bs.getEnemyBackRowTargets(caster)
	case model.TargetEnemyAll: // 敌方全体
		return bs.getAllEnemyTargets(caster)
	case model.TargetAllySingle:
		return bs.getSingleSelfTarget(caster)
	case model.TargetAllyAll: // 友方全体
		return bs.getAllAllyTargets(caster)
	case model.TargetSelf: // 自身
		return []*model.FightHero{caster}
	default:
		return bs.getSingleEnemyTarget(caster)
	}
}

// 获取敌方前排目标
func (bs *BattleSystem) getEnemyFrontRowTargets(caster *model.FightHero) []*model.FightHero {
	enemyPlayerID := bs.getEnemyPlayerID(caster.PlayerId)
	return bs.Battle.GetFrontRowHeroes(enemyPlayerID)
}

// 获取敌方后排目标
func (bs *BattleSystem) getEnemyBackRowTargets(caster *model.FightHero) []*model.FightHero {
	enemyPlayerID := bs.getEnemyPlayerID(caster.PlayerId)
	return bs.Battle.GetBackRowHeroes(enemyPlayerID)
}

// 获取所有敌方目标
func (bs *BattleSystem) getAllEnemyTargets(caster *model.FightHero) []*model.FightHero {
	enemyPlayerID := bs.getEnemyPlayerID(caster.PlayerId)
	return bs.Battle.GetAllAliveHeroes(enemyPlayerID)
}

// 获取生命值最低的友方目标
func (bs *BattleSystem) getLowestHpAllyTarget(caster *model.FightHero) []*model.FightHero {
	allies := bs.Battle.GetAllAliveHeroes(caster.PlayerId)
	if len(allies) == 0 {
		return []*model.FightHero{}
	}

	// 找出生命值百分比最低的友方
	lowestHpHero := allies[0]
	lowestHpPercentage := float64(lowestHpHero.CurrentHp) / float64(lowestHpHero.MaxHp)

	for _, ally := range allies {
		hpPercentage := float64(ally.CurrentHp) / float64(ally.MaxHp)
		if hpPercentage < lowestHpPercentage {
			lowestHpHero = ally
			lowestHpPercentage = hpPercentage
		}
	}

	return []*model.FightHero{lowestHpHero}
}

// 获取所有友方目标
func (bs *BattleSystem) getAllAllyTargets(caster *model.FightHero) []*model.FightHero {
	return bs.Battle.GetAllAliveHeroes(caster.PlayerId)
}

// 获取友方单体
func (bs *BattleSystem) getSingleSelfTarget(caster *model.FightHero) []*model.FightHero {
	aliveHeroes := bs.Battle.GetAllAliveHeroes(caster.PlayerId)
	if len(aliveHeroes) == 0 {
		return []*model.FightHero{}
	}
	// 随机选择一个敌人
	targetIndex := bs.RNG.Intn(len(aliveHeroes))
	return []*model.FightHero{aliveHeroes[targetIndex]}
}

// 获取单个敌方目标
func (bs *BattleSystem) getSingleEnemyTarget(caster *model.FightHero) []*model.FightHero {
	enemyPlayerID := bs.getEnemyPlayerID(caster.PlayerId)
	enemies := bs.Battle.GetAllAliveHeroes(enemyPlayerID)
	if len(enemies) == 0 {
		return []*model.FightHero{}
	}

	// 随机选择一个敌人
	targetIndex := bs.RNG.Intn(len(enemies))
	return []*model.FightHero{enemies[targetIndex]}
}

// 获取敌方玩家ID
func (bs *BattleSystem) getEnemyPlayerID(playerID int) int {
	if playerID == bs.Battle.PlayerId1 {
		return bs.Battle.PlayerId2
	}
	return bs.Battle.PlayerId1
}

// 选择攻击目标
func (bs *BattleSystem) selectAttackTarget(attacker *model.FightHero) *model.FightHero {
	// 优先攻击前排
	frontRowTargets := bs.getEnemyFrontRowTargets(attacker)
	if len(frontRowTargets) > 0 {
		// 随机选择一个前排目标
		targetIndex := bs.RNG.Intn(len(frontRowTargets))
		return frontRowTargets[targetIndex]
	}

	// 如果前排没有目标，攻击后排
	backRowTargets := bs.getEnemyBackRowTargets(attacker)
	if len(backRowTargets) > 0 {
		// 随机选择一个后排目标
		targetIndex := bs.RNG.Intn(len(backRowTargets))
		return backRowTargets[targetIndex]
	}

	return nil // 没有可攻击的目标
}

// 计算伤害
func (bs *BattleSystem) calculateDamage(attacker, defender *model.FightHero, baseDamage float64, isSkill bool) (int, bool) {
	// 基础伤害
	damage := baseDamage

	// todo 考虑攻击者的物理，魔法等修改damage的增益，和被攻击方的减益

	// 考虑防御
	defense := float64(defender.Defense)
	// todo 护甲穿透

	damage = damage * (100 / (100 + defense))

	// 考虑暴击
	isCrit := bs.rollCrit(attacker.CritRate)
	if isCrit {
		damage = damage * attacker.CritDamage
	}

	// 考虑伤害减免
	damage = damage * (1 - defender.DamageReduction)

	return int(damage), isCrit
}

// 判断是否暴击
func (bs *BattleSystem) rollCrit(critRate float64) bool {
	return bs.RNG.Float64() < critRate
}

// 应用伤害
func (bs *BattleSystem) applyDamage(attacker, target *model.FightHero, damage int) {
	// 应用伤害
	target.CurrentHp -= damage

	// 检查是否死亡
	if target.CurrentHp <= 0 {
		target.CurrentHp = 0
		target.IsAlive = false

		deathMsg := fmt.Sprintf("英雄 %s 阵亡！", target.HeroName)
		bs.logBattleAction("hero_death", target.HeroId, nil, nil, deathMsg)
	}
}

// 更新技能CD
func (bs *BattleSystem) updateSkillCDs(hero *model.FightHero) {
	for skillID, cd := range hero.SkillCDs {
		if cd > 0 {
			hero.SkillCDs[skillID]--
		}
	}
}

// 回合结束处理
func (bs *BattleSystem) endRound() {
	// 处理持续效果
	for _, heroPositions := range bs.Battle.FightHeroes {
		for _, hero := range heroPositions {
			if !hero.IsAlive {
				continue
			}

			// 更新buff持续时间
			newBuffs := make([]model.Effect, 0)
			for _, effect := range hero.Buffs {
				if effect.Duration > 0 {
					effect.Duration--
					if effect.Duration > 0 {
						newBuffs = append(newBuffs, effect)
					} else {
						buffExpireMsg := fmt.Sprintf("英雄 %s 的 %s 效果已结束", hero.HeroName, effect.Description)
						bs.logBattleAction("buff_expire", hero.HeroId, nil, nil, buffExpireMsg)
					}
				}
			}
			hero.Buffs = newBuffs

			// 更新deBuff持续时间
			newDeBuffs := make([]model.Effect, 0)
			for _, effect := range hero.Debuffs {
				if effect.Duration > 0 {
					effect.Duration--
					if effect.Duration > 0 {
						newDeBuffs = append(newDeBuffs, effect)
					} else {
						debuffExpireMsg := fmt.Sprintf("英雄 %s 的 %s 效果已结束", hero.HeroName, effect.Description)
						bs.logBattleAction("debuff_expire", hero.HeroId, nil, nil, debuffExpireMsg)
					}
				}
			}
			hero.Debuffs = newDeBuffs
		}
	}

	roundEndMsg := fmt.Sprintf("第%d回合结束", bs.CurrentRound)
	bs.logBattleAction("round_end", 0, nil, nil, roundEndMsg)
}

// 记录战斗日志
func (bs *BattleSystem) logBattleAction(actionType string, actorId int, targetIds []int, skillIds []int, message string) {
	logEntry := model.BattleLogEntry{
		Round:      bs.CurrentRound,
		Timestamp:  time.Now(),
		ActorId:    actorId,
		TargetIds:  targetIds,
		ActionType: actionType,
		Message:    message,
	}

	if skillIds != nil && len(skillIds) > 0 {
		logEntry.SkillId = skillIds[0]
	}

	bs.Battle.BattleLog = append(bs.Battle.BattleLog, logEntry)
}

// 检查战斗是否结束
func (bs *BattleSystem) checkBattleEnd() bool {
	// 检查玩家1是否全部阵亡
	player1Alive := len(bs.Battle.GetAllAliveHeroes(bs.Battle.PlayerId1)) > 0

	// 检查玩家2是否全部阵亡
	player2Alive := len(bs.Battle.GetAllAliveHeroes(bs.Battle.PlayerId2)) > 0

	// 如果有一方全部阵亡，战斗结束
	if !player1Alive || !player2Alive {
		if !player1Alive {
			bs.Battle.Winner = bs.Battle.PlayerId2
			winMsg := fmt.Sprintf("玩家 %d 获胜！", bs.Battle.PlayerId2)
			bs.logBattleAction("battle_end", 0, nil, nil, winMsg)
		} else {
			bs.Battle.Winner = bs.Battle.PlayerId1
			winMsg := fmt.Sprintf("玩家 %d 获胜！", bs.Battle.PlayerId1)
			bs.logBattleAction("battle_end", 0, nil, nil, winMsg)
		}
		bs.Battle.Status = "finished"
		bs.Battle.EndTime = time.Now()
		return true
	}

	return false
}

// BattleResult 战斗结果
type BattleResult struct {
	BattleId     string                 // 战斗ID
	Winner       int                    // 获胜方ID
	Duration     int                    // 战斗持续回合数
	TotalTime    time.Duration          // 战斗总时长
	DamageStats  map[int]int            // 各英雄造成的伤害统计
	HealingStats map[int]int            // 各英雄治疗量统计
	Survivors    []*model.FightHero     // 存活的英雄
	BattleLog    []model.BattleLogEntry // 战斗日志
}

// 生成战斗结果
func (bs *BattleSystem) generateBattleResult() *BattleResult {
	// 计算伤害和治疗统计
	damageStats := make(map[int]int)
	healingStats := make(map[int]int)

	for _, entry := range bs.Battle.BattleLog {
		if entry.ActionType == "hero_attack" || entry.ActionType == "skill_damage" {
			damageStats[entry.ActorId] += entry.Damage
		}
		if entry.ActionType == "skill_heal" {
			healingStats[entry.ActorId] += entry.Healing
		}
	}

	// 收集存活英雄
	survivors := make([]*model.FightHero, 0)
	for _, heroPositions := range bs.Battle.FightHeroes {
		for _, hero := range heroPositions {
			if hero.IsAlive {
				survivors = append(survivors, hero)
			}
		}
	}

	return &BattleResult{
		BattleId:     bs.Battle.BattleId,
		Winner:       bs.Battle.Winner,
		Duration:     bs.CurrentRound,
		TotalTime:    bs.Battle.EndTime.Sub(bs.Battle.StartTime),
		DamageStats:  damageStats,
		HealingStats: healingStats,
		Survivors:    survivors,
		BattleLog:    bs.Battle.BattleLog,
	}
}

// 辅助函数：取两个整数的最小值
func min(a, b int) int {
	if a < b {
		return a
	}
	return b
}
